package utils

import (
	"fmt"
	_ "fmt"
	"study/14_practice_chat/common"

	"encoding/binary"
	"encoding/json"
	"net"
)

// 读请求体
func ReadRequest(conn net.Conn) (request common.RequestBody, err error) {
	var pkgLen int
	pkgLen, err = readHeadLen(conn) // 1. 读取包长度
	if pkgLen == 0 || err != nil {
		return
	}
	err = readBody(conn, pkgLen, &request) // 2. 读取消息体
	return
}

// 写请求
func WriteRequest(conn net.Conn, request common.RequestBody) (err error) {
	// 1. 序列化
	jsonBytes, err := json.Marshal(request)
	// 2. 写包长度
	err = writePkgLen(conn, uint32(len(jsonBytes)))
	if err != nil {
		return
	}
	// 3. 写入消息体
	_, err = conn.Write(jsonBytes)
	return
}

// 读取响应体
func ReadResponse(conn net.Conn) (response common.ResponseBody, err error) {
	var pkgLen int
	pkgLen, err = readHeadLen(conn) // 1. 读取包长度
	if pkgLen == 0 || err != nil {
		return
	}
	err = readBody(conn, pkgLen, &response) // 2. 读取消息体
	return
}

// 写响应
func WriteResponse(conn net.Conn, response common.ResponseBody) (err error) {
	// 1. 序列化
	jsonBytes, err := json.Marshal(response)
	// 2. 写包长度
	err = writePkgLen(conn, uint32(len(jsonBytes)))
	if err != nil {
		return
	}
	// 3. 写入消息体
	_, err = conn.Write(jsonBytes)
	return
}

func writePkgLen(conn net.Conn, pkgLen uint32) (err error) {
	pkgLenBytes := make([]byte, 4)
	binary.BigEndian.PutUint32(pkgLenBytes, pkgLen)
	_, err = conn.Write(pkgLenBytes)
	if err != nil {
		fmt.Println("write pkg length error !", err)
		return
	}
	return
}

// 读取消息体长度
func readHeadLen(conn net.Conn) (pkgLen int, err error) {
	buf := make([]byte, 4) // 消息长度是int32类型是4个字节
	_, err = conn.Read(buf)
	if err != nil {
		fmt.Println("read request body head error : ", err)
		return
	}
	pkgLen = int(binary.BigEndian.Uint32(buf[0:4])) // 读取的字节切片转化int
	return
}

/*
读取消息体并反序列化为对应的结构体
*/
func readBody(conn net.Conn, pkgLen int, targetStructAddress interface{}) (err error) {
	if pkgLen < 0 {
		pkgLen = 1024 * 4 // 默认给4KB缓存
	}
	buf := make([]byte, pkgLen)
	var readLen int
	readLen, err = conn.Read(buf)
	if pkgLen != readLen && err != nil {
		fmt.Printf("read request body error ,maby is body not equals %d, or internal error : %v\n", readLen, err)
		return
	}
	err = deserializedJsonString(targetStructAddress, buf)
	return
}

// 反序列化JSON为指定任意类型
// stu : 被序列化的结构体的地址
// jsonBytes : json字符串的字节数组
func deserializedJsonString(targetStructAddress interface{}, jsonBytes []byte) (err error) {
	err = json.Unmarshal(jsonBytes, targetStructAddress)
	return
}
